/*
 * ImageBrowser.java
 *
 * Created on 19 avril 2007, 21:16
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package courselog;

import ewe.fx.Color;
import ewe.fx.Graphics;
import ewe.fx.IImage;
import ewe.fx.Image;
import ewe.fx.ImageData;
import ewe.fx.ImageTool;
import ewe.fx.Pen;
import ewe.fx.Point;
import ewe.fx.Rect;
import ewe.ui.Control;

/**
 *
 * @author rigal
 */
public class ImageBrowser extends AbstractImageDisplay {
    
    /**
     * CenterReticule
     */
    public static final int[] tiReticuleX= new int[]{-8,-2,2,8,0,0,0,0};
    public static final int[] tiReticuleY= new int[]{0,0,0,0,-8,-2,2,8};
    
    /**
     * Reticule pen.
     */
    public static final Pen pReticule= new Pen(Color.Black,Pen.SOLID,1);
    
    /** Indicator to set if a reticule is wanted. False at initialisation.
     */
    public boolean isReticuleOn=false;
    
    /** Base image data for Image operations.
     */
    public ImageData baseImageData=null;
    
    /** Base drawable image.
     */
    public IImage baseIImage=null;
    
    /**
     * Center X offset in control coordinates.
     */
    protected int centerX=0;
    
    /**
     * Center Y offset in control coordinates.
     */
    protected int centerY=0;
    
    /**
     * Scaling of display image.
     */
    protected double scaleDisplay=1.0d;
    
    /**
     * Creates a new empty instance of ImageBrowser without an image file.
     */
    public ImageBrowser() {
        this.modify(Control.TakesKeyFocus|Control.WantHoldDown,0);
    }
    
    /**
     * Creates a new instance of ImageBrowser from an image file.
     * @param imagePath Path to image file.
     */
    public ImageBrowser(String imagePath) {
        Image img=new Image(imagePath);
        setBaseImage(img,img);
        this.modify(Control.TakesKeyFocus|Control.WantHoldDown,0);
    }
    
    // Class methods
    
    /**
     * Set base of this ImageBrowser from an image interface.
     * @param img Drawable image to use as base.
     */
    public void setBaseImage(IImage img) {
        ImageData imgD=ImageTool.toImageData(img);
        setBaseImage(imgD,img);
    }
    
    public void setBaseImage(ImageData datImg, IImage newIImage) {
        baseImageData= datImg;
        baseIImage= newIImage;
        this.centerX=baseIImage.getWidth()/2;
        this.centerY=baseIImage.getHeight()/2;
        this.scaleDisplay=1.0d;
        this.setPreferredSize(baseIImage.getWidth(),baseIImage.getHeight());
    }
    
    /**
     * Transform a set of (x,y) coordinates in base image to a Point
     * with (x,y) coordinates in displayed image.
     */
    public Point baseToDisplay(int x, int y, Point dest) {
        if(dest==null) {
            dest=new Point();
        }
        dest.x=(int) ((x-centerX)*scaleDisplay+dispImage.getWidth()/2+0.5d);
        dest.y=(int) ((y-centerY)*scaleDisplay+dispImage.getHeight()/2+0.5d);
        
        return dest;
    }
    
    /**
     * Transform a set of (x,y) coordinates in displayed image to a Point
     * with (x,y) coordinates in base image.
     */
    public Point displayToBase(int x, int y, Point dest) {
        if(dest==null) {
            dest=new Point();
        }
        if(dispImage!=null) {
            dest.x=(int) ((x-iOX-dispImage.getWidth()/2)/scaleDisplay+centerX+0.5d);
            dest.y=(int) ((y-iOY-dispImage.getHeight()/2)/scaleDisplay+centerY+0.5d);
        }
        return dest;
    }
    
    // Implementation of ABSTRACT METHODS
    
    /**
     * Update image. The option value is not used.
     */
    public void updateDisplayedImage(Rect r, int opt) {
        if((width==0)||(height==0)||(baseIImage==null)) {
            return;
        }
        
        int iT;
        
        int iBaseWidth=baseIImage.getWidth();
        int iBaseHeight=baseIImage.getHeight();
        
        int iOriginW = (int) (width/scaleDisplay+0.5d);
        int iOriginH = (int) (height/scaleDisplay+0.5d);
        
        if(iOriginW>iBaseWidth) iOriginW=iBaseWidth;
        if(iOriginW<=0) iOriginW=1;
        if(iOriginH>iBaseHeight) iOriginH=iBaseHeight;
        if(iOriginH<=0) iOriginH=1;
        
        centerX= (int) (centerX-iOX/scaleDisplay+0.5d);
        centerY= (int) (centerY-iOY/scaleDisplay+0.5d);
        
        int iTopLeftX= (int) (centerX-iOriginW/2+0.5d);
        int iTopLeftY= (int) (centerY-iOriginH/2+0.5d);
        
        // Recompute center if the displayed image goes out of the base
        if(iTopLeftX<0) {
            centerX -= iTopLeftX;
            iTopLeftX=0;
        }
        
        iT= iTopLeftX+iOriginW-iBaseWidth;
        if(iT>0) {
            centerX -= iT;
            iTopLeftX -=iT;
        }
        
        if(iTopLeftY<0) {
            centerY -= iTopLeftY;
            iTopLeftY=0;
        }
        iT= iTopLeftY+iOriginH-iBaseHeight;
        if(iT>0) {
            centerY -=iT;
            iTopLeftY -=iT;
        }
        
        // Create display image
        int iScaledW = (int) (iBaseWidth*scaleDisplay);
        int iScaledH = (int) (iBaseHeight*scaleDisplay);
        int iScaledX = (int) (iTopLeftX*scaleDisplay);
        int iScaledY = (int) (iTopLeftY*scaleDisplay);
        int iDispW = (int) (iOriginW*scaleDisplay);
        int iDispH = (int) (iOriginH*scaleDisplay);
        if(dispImage!=null) {
            if((dispImage.getWidth()!=iDispW)||(dispImage.getHeight()!=iDispH)) {
                dispImage.free();
                dispImage=ImageTool.createCompatibleImage(baseImageData,iDispW,iDispH);
            }
        }else{
            dispImage=ImageTool.createCompatibleImage(baseImageData,iDispW,iDispH);
        }
        /* scaleSection parameters :
         * baseImage : source image
         * iScaledW : Width of the complete source image after scaling
         * iScaledH : Height of the complete source image after scaling
         * dispImage : destination image
         * iScaledX : X of top left corner of the destination in the scaled source
         * iScaledY : Y of top left corner of the destination in the scaled source
         * SCALE_KEEP_ASPECT_RATIO : option to keep aspect ratio.
         */
        
        ImageTool.scaleSection(baseImageData,iScaledW,iScaledH,dispImage,
                iScaledX,iScaledY,ImageTool.SCALE_KEEP_ASPECT_RATIO);
        
        // recompute center position in the control
        iOX = (int) ((width-iDispW)/2+0.5d);
        iOY = (int) ((height-iDispH)/2+0.5d);
        
        //CourseLogAppForm.dbgL.setLog("dW= "+iDispW+", dH"+iDispH+" OX "+iTopLeftX+", OY "+iTopLeftY);
        //CourseLogAppForm.dbgL.addToLog("\ncenter= "+centerX+","+centerY+") ODisp "+iOX+","+iOY);
        repaint();
    }
    
    public void actionOnLeftAppButton() {
        //CourseLogAppForm.dbgL.addToLog("\nImageBrowser.leftButtonPressed()");
    }
    
    public void actionOnRightAppButton() {
        //CourseLogAppForm.dbgL.addToLog("\nImageBrowser.rightButtonPressed()");
    }
    
    public void actionOnPenHeld(Point p) {
        //CourseLogAppForm.dbgL.addToLog("\nImageBrowser.actionOnPenHeld("+p.x+","+p.y+")");
        updateDisplayedImage(null,0);
    }
    
    
    public void actionOnPenClick(Point p) {
        //CourseLogAppForm.dbgL.addToLog("\nImageBrowser.actionOnPenClick("+p.x+","+p.y+")");
//        if(CourseLogAppForm.dbgL.isLogFreezed()) {
//            CourseLogAppForm.dbgL.unFreezeLog();
//        }else{
//            CourseLogAppForm.dbgL.freezeLog();
//        }
    }
    
    public void rescaleImage(double byFactor) {
        if(baseIImage==null) return;
        
        if(byFactor>1) {
            if((dispImage.getHeight()/scaleDisplay)>(16*byFactor)) {
                scaleDisplay *= byFactor;
            }
        }else{
            if((baseIImage.getHeight()*scaleDisplay)>(64/byFactor)) {
                scaleDisplay *= byFactor;
            }
        }
    }
    
    
    // Overriden methods
    
    public void resizeTo(int width, int height) {
        this.width=width;
        this.height=height;
        updateDisplayedImage(null,0);
    }
    
    public void doPaint(Graphics g, Rect r) {
        super.doPaint(g,r);
        
        if(isReticuleOn) {
            // Draw reticule
            g.setDrawOp(Graphics.DRAW_XOR);
            g.setPen(pReticule);
            int midX=(int) (width/2);
            int midY=(int) (height/2);
            for(int i=0; i<tiReticuleX.length; i +=2) {
                g.drawLine(tiReticuleX[i]+midX,tiReticuleY[i]+midY,
                        tiReticuleX[i+1]+midX,tiReticuleY[i+1]+midY);
            }
        }
    }
    
}
